#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#include "delay.h"

// OLED显存格式
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127

/**********************************************
//IIC Start
**********************************************/
void IIC_Start(void)
{

	OLED_SCLK_Set();
	OLED_SDIN_Set();
	OLED_SDIN_Clr();
	OLED_SCLK_Clr();
}

/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop(void)
{
	OLED_SCLK_Set();
	OLED_SDIN_Clr();
	OLED_SDIN_Set();
}

void IIC_Wait_Ack(void)
{

	// GPIOB->CRH &= 0XFFF0FFFF;	//����PB12Ϊ��������ģʽ
	// GPIOB->CRH |= 0x00080000;
	//	OLED_SDA = 1;
	//	delay_us(1);
	// OLED_SCL = 1;
	// delay_us(50000);
	/*	while(1)
		{
			if(!OLED_SDA)				//�ж��Ƿ���յ�OLED Ӧ���ź�
			{
				//GPIOB->CRH &= 0XFFF0FFFF;	//����PB12Ϊͨ���������ģʽ
				//GPIOB->CRH |= 0x00030000;
				return;
			}
		}
	*/
	OLED_SCLK_Set();
	OLED_SCLK_Clr();
}

/**********************************************
// IIC Write byte
**********************************************/
void Write_IIC_Byte(unsigned char IIC_Byte)
{
	unsigned char i, byte, data;
	data = IIC_Byte;
	OLED_SCLK_Clr();
	for (i = 0; i < 8; i++)
	{
		byte = data;
		// �Ը�λ�ֽ���1ȡ��
		byte = byte & 0x80;
		if (byte == 0x80)
			OLED_SDIN_Set();
		else
			OLED_SDIN_Clr();
		OLED_SCLK_Set();
		OLED_SCLK_Clr();
		data <<= 1;
	}
}

/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
	IIC_Start();
	Write_IIC_Byte(0x78); // 0111 1000��Slave address��SA0=0��I2C�ӻ���ַ
	IIC_Wait_Ack();
	Write_IIC_Byte(0x00); // 0000 0000��д�����write command
	IIC_Wait_Ack();
	Write_IIC_Byte(IIC_Command);
	IIC_Wait_Ack();
	IIC_Stop();
}

/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
	IIC_Start();
	Write_IIC_Byte(0x78); //  0111 1000,D/C#=0; R/W#=0��I2C�ӻ���ַ
	IIC_Wait_Ack();
	Write_IIC_Byte(0x40); //  0100 0000��д�����ݣ�write data
	IIC_Wait_Ack();
	Write_IIC_Byte(IIC_Data);
	IIC_Wait_Ack();
	IIC_Stop();
}

void OLED_WR_Byte(unsigned dat, unsigned cmd)
{
	if (cmd)
		Write_IIC_Data(dat);
	else
		Write_IIC_Command(dat);
}

/********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{
	unsigned char m, n;
	for (m = 0; m < 8; m++)
	{
		OLED_WR_Byte(0xb0 + m, OLED_CMD); // 1011 0000��page0-page1
		OLED_WR_Byte(0x00, OLED_CMD);	  // low column start address
		OLED_WR_Byte(0x10, OLED_CMD);	  // high column start address
		for (n = 0; n < 128; n++)
			OLED_WR_Byte(fill_Data, OLED_DATA);
	}
}

/***********************Delay****************************************/
void Delay_50ms(unsigned int Del_50ms)
{
	unsigned int m;
	for (; Del_50ms > 0; Del_50ms--)
		for (m = 6245; m > 0; m--)
			;
}

void Delay_1ms(unsigned int Del_1ms)
{
	unsigned char j;
	while (Del_1ms--)
	{
		for (j = 0; j < 123; j++)
			;
	}
}

// ��������
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
	OLED_WR_Byte(0xb0 + y, OLED_CMD);
	OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
	OLED_WR_Byte((x & 0x0f), OLED_CMD);
}
// ����OLED��ʾ
void OLED_Display_On(void)
{
	OLED_WR_Byte(0X8D, OLED_CMD); // SET DCDC����
	OLED_WR_Byte(0X14, OLED_CMD); // DCDC ON
	OLED_WR_Byte(0XAF, OLED_CMD); // DISPLAY ON
}
// �ر�OLED��ʾ
void OLED_Display_Off(void)
{
	OLED_WR_Byte(0X8D, OLED_CMD); // SET DCDC����
	OLED_WR_Byte(0X10, OLED_CMD); // DCDC OFF
	OLED_WR_Byte(0XAE, OLED_CMD); // DISPLAY OFF
}
// ��������,������,������Ļ�Ǻ�ɫ��!��û����һ��!!!
void OLED_Clear(void)
{
	u8 i, n;
	for (i = 0; i < 8; i++)
	{
		OLED_WR_Byte(0xb0 + i, OLED_CMD); // ����ҳ��ַ��0~7��
		OLED_WR_Byte(0x00, OLED_CMD);	  // ������ʾλ�á��е͵�ַ
		OLED_WR_Byte(0x10, OLED_CMD);	  // ������ʾλ�á��иߵ�ַ
		for (n = 0; n < 128; n++)
			OLED_WR_Byte(0, OLED_DATA);
	} // ������ʾ
}

void OLED_ClearRow(u8 row)
{
	u8 i, n;
	for (i = row; i < 2; i++)
	{
		OLED_WR_Byte(0xb0 + i, OLED_CMD); // ����ҳ��ַ��0~7��
		OLED_WR_Byte(0x00, OLED_CMD);	  // ������ʾλ�á��е͵�ַ
		OLED_WR_Byte(0x10, OLED_CMD);	  // ������ʾλ�á��иߵ�ַ
		for (n = 0; n < 128; n++)
			OLED_WR_Byte(0, OLED_DATA); // ������ʾ
	}
}

void OLED_On(void)
{
	u8 i, n;
	for (i = 0; i < 8; i++)
	{
		OLED_WR_Byte(0xb0 + i, OLED_CMD); // ����ҳ��ַ��0~7��
		OLED_WR_Byte(0x00, OLED_CMD);	  // ������ʾλ�á��е͵�ַ
		OLED_WR_Byte(0x10, OLED_CMD);	  // ������ʾλ�á��иߵ�ַ
		for (n = 0; n < 128; n++)
			OLED_WR_Byte(1, OLED_DATA);
	} // ������ʾ
}
// ��ָ��λ����ʾһ���ַ�,���������ַ�
// x:0~127
// y:0~63
// mode:0,������ʾ;1,������ʾ
// size:ѡ������ 16/12
void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 Char_Size)
{
	unsigned char c = 0, i = 0;
	c = chr - ' '; // �õ�ƫ�ƺ��ֵ
	if (x > Max_Column - 1)
	{
		x = 0;
		y = y + 2;
	}
	if (Char_Size == 16)
	{
		OLED_Set_Pos(x, y);
		for (i = 0; i < 8; i++)
			OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);
		OLED_Set_Pos(x, y + 1);
		for (i = 0; i < 8; i++)
			OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
	}
	else
	{
		OLED_Set_Pos(x, y);
		for (i = 0; i < 6; i++)
			OLED_WR_Byte(F6x8[c][i], OLED_DATA);
	}
}
// m^n����
u32 oled_pow(u8 m, u8 n)
{
	u32 result = 1;
	while (n--)
		result *= m;
	return result;
}
// ��ʾ2������
// x,y :�������
// len :���ֵ�λ��
// size:�����С
// mode:ģʽ	0,���ģʽ;1,����ģʽ
// num:��ֵ(0~4294967295);
void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 size2)
{
	u8 t, temp;
	u8 enshow = 0;
	for (t = 0; t < len; t++)
	{
		temp = (num / oled_pow(10, len - t - 1)) % 10;
		if (enshow == 0 && t < (len - 1))
		{
			if (temp == 0)
			{
				OLED_ShowChar(x + (size2 / 2) * t, y, ' ', size2);
				continue;
			}
			else
				enshow = 1;
		}
		OLED_ShowChar(x + (size2 / 2) * t, y, temp + '0', size2);
	}
}
// ��ʾһ���ַ��Ŵ�
void OLED_ShowString(u8 x, u8 y, u8 *chr, u8 Char_Size)
{
	unsigned char j = 0;
	while (chr[j] != '\0')
	{
		OLED_ShowChar(x, y, chr[j], Char_Size);
		x += 8;
		if (x > 120)
		{
			x = 0;
			y += 2;
		}
		j++;
	}
}
// ��ʾ����
void OLED_ShowCHinese(u8 x, u8 y, u8 no)
{
	u8 t, adder = 0;
	OLED_Set_Pos(x, y);
	for (t = 0; t < 16; t++)
	{
		OLED_WR_Byte(Hzk[2 * no][t], OLED_DATA);
		adder += 1;
	}
	OLED_Set_Pos(x, y + 1);
	for (t = 0; t < 16; t++)
	{
		OLED_WR_Byte(Hzk[2 * no + 1][t], OLED_DATA);
		adder += 1;
	}
}
/***********������������ʾ��ʾBMPͼƬ128��64��ʼ������(x,y),x�ķ�Χ0��127��yΪҳ�ķ�Χ0��7*****************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char BMP[])
{
	unsigned int j = 0;
	unsigned char x, y;

	if (y1 % 8 == 0)
		y = y1 / 8;
	else
		y = y1 / 8 + 1;

	for (y = y0; y < y1; y++)
	{
		OLED_Set_Pos(x0, y);
		for (x = x0; x < x1; x++)
			OLED_WR_Byte(BMP[j++], OLED_DATA);
	}
}

// ���������ƶ�
void OLED_RightDrawBMP(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char BMP[], unsigned char NBMP[])
{
	unsigned int i = 0;
	unsigned char x, y;
	unsigned char bmp_weight = x1 - x0;
	unsigned char flag = bmp_weight;

	for (i = 0; i < bmp_weight; i += 4)
	{
		for (x = x0; x < x1; x++)
		{
			for (y = y0; y < y1; y++)
			{
				OLED_Set_Pos(x, y1 - y - 1 + y0);
				if ((x - x0) < flag)
					OLED_WR_Byte(BMP[(bmp_weight - flag) + x - x0 + ((y1 - y - 1) * bmp_weight)], OLED_DATA);
				else
					OLED_WR_Byte(NBMP[x - x0 - flag + ((y1 - y - 1) * bmp_weight)], OLED_DATA);
			}
		}
		flag -= 4;
	}
}

// ���������ƶ�
void OLED_LeftDrawBMP(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char BMP[], unsigned char NBMP[])
{
	unsigned int i = 0;
	unsigned char x, y;
	unsigned char bmp_weight = x1 - x0;
	unsigned char flag = bmp_weight;

	for (i = 0; i < bmp_weight; i += 4)
	{
		for (x = x0; x < x1; x++)
		{
			for (y = y0; y < y1; y++)
			{
				OLED_Set_Pos(x, y1 - y - 1 + y0);
				if ((x - x0) < (bmp_weight - flag))
					OLED_WR_Byte(NBMP[(flag + x - x0) + ((y1 - y - 1) * bmp_weight)], OLED_DATA);
				else
					OLED_WR_Byte(BMP[(flag - bmp_weight) + x - x0 + ((y1 - y - 1) * bmp_weight)], OLED_DATA);
			}
		}
		flag -= 4;
	}
}

/*
// ���ٻ���ͼ��
void OLED_DrawBMPFast(const unsigned char BMP[])
{
	unsigned int j = 0;
	unsigned char x, y;

	for (y = 0; y < 8; y++)
	{
		OLED_Set_Pos(0, y);
		IIC_Start();
		Write_IIC_Byte(0x78);
		IIC_Wait_Ack();
		Write_IIC_Byte(0x40);
		IIC_Wait_Ack();
		for (x = 0; x < 128; x++)
		{
			Write_IIC_Byte(BMP[j++]);
			IIC_Wait_Ack();
		}
		IIC_Stop();
	}
}
*/

void OLED_DrawGIF(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char k, int m, unsigned char GIF[][m])
{
	unsigned int j = 0;	   // �������
	unsigned char x, y, i; // �������

	if (y1 % 8 == 0)
		y = y1 / 8; // �ж���ֹҳ�Ƿ�Ϊ8��������
	else
		y = y1 / 8 + 1;
	for (i = 0; i < k; i++) // �ӵ�һ֡��ʼ��
	{
		j = 0;
		for (y = y0; y < y1; y++) // ����ʼҳ��ʼ��������ֹҳ
		{
			OLED_Set_Pos(x0, y); // ��ҳ����ʼ�п�ʼ��

			for (x = x0; x < x1; x++) // ��x1 - x0 ��
			{
				OLED_WR_Byte(GIF[i][j++], OLED_DATA); // ��ͼƬ�ĵ�
			}
		}
		// delay_ms(80);//��Ϊ���쿨�٣�����
	}
}

// ��ʼ��SSD1306
void OLED_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(OLED_SCLK_CLK | OLED_SDIN_CLK, ENABLE); // ʹ��PC,D,G�˿�ʱ��

	GPIO_InitStructure.GPIO_Pin = OLED_SCLK_PIN;	  // PD3,PD6�������
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // �������
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // �ٶ�50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);			  // ��ʼ��GPIOD3,6
	GPIO_SetBits(OLED_SCLK_PORT, OLED_SCLK_PIN);	  // PD3,PD6 �����

	GPIO_InitStructure.GPIO_Pin = OLED_SDIN_PIN;	  // PD3,PD6�������
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // �������
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // �ٶ�50MHz
	GPIO_Init(OLED_SDIN_PORT, &GPIO_InitStructure);	  // ��ʼ��GPIOD3,6
	GPIO_SetBits(OLED_SDIN_PORT, OLED_SDIN_PIN);	  // PD3,PD6 �����

	delay_ms(200);

	OLED_WR_Byte(0xA8, OLED_CMD); // ����MUX����·������������ΪN+1
	OLED_WR_Byte(0x3F, OLED_CMD); // MUX ����Ϊ3FH+1 MUX��Ĭ�ϣ�

	OLED_WR_Byte(0xD3, OLED_CMD); // ������Ļ��ֱƫ����
	OLED_WR_Byte(0x00, OLED_CMD); // ƫ����0��0-63��

	OLED_WR_Byte(0x40, OLED_CMD); // ��Ļ��ʼ�У�40H-7FH��Ӧ0-63��

	OLED_WR_Byte(0xA1, OLED_CMD); // ���û�����ӳ�䣨A0HĬ��ֵ��

	OLED_WR_Byte(0xC8, OLED_CMD); //-not offset

	OLED_WR_Byte(0xDA, OLED_CMD); // ����COM����Ӳ�����ã�DAH��
	OLED_WR_Byte(0x12, OLED_CMD); // ����Ϊ02

	OLED_WR_Byte(0x81, OLED_CMD); // ���öԱȶ�
	OLED_WR_Byte(0xFF, OLED_CMD);

	OLED_WR_Byte(0xA4, OLED_CMD); // �ָ���ʾRAM���ݣ�A4H��

	OLED_WR_Byte(0xA6, OLED_CMD); // ����Ϊ��ͨ��ʾ
	// OLED_WR_Byte(0xA7,OLED_CMD);//����Ϊ������ʾ

	OLED_WR_Byte(0xD5, OLED_CMD); // ������Ƶ�ʺͷ�Ƶϵ����D5H��
	OLED_WR_Byte(0xF0, OLED_CMD); // ����Ƶ��Ϊ8H��0000-1111����Ƶ0H

	OLED_WR_Byte(0x8d, OLED_CMD); // ʹ�ܵ����ѹ����8DH��
	OLED_WR_Byte(0x14, OLED_CMD); // ģʽ14H

	OLED_WR_Byte(0xAF, OLED_CMD); // ������Ļ
	OLED_Clear();
	/*****
	OLED_WR_Byte(0xAE,OLED_CMD);//�ر���ʾ

	OLED_WR_Byte(0xa6,OLED_CMD);//

	OLED_WR_Byte(0xd9,OLED_CMD);
	OLED_WR_Byte(0x22,OLED_CMD);

	OLED_WR_Byte(0xda,OLED_CMD);
	OLED_WR_Byte(0x02,OLED_CMD);

	OLED_WR_Byte(0xdb,OLED_CMD);
	OLED_WR_Byte(0x49,OLED_CMD);
	*****/
}
